package com.tbit.uqbike.client.service.impl;

import com.tbit.uqbike.client.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service("redisService")
@Slf4j
public class RedisServiceImpl implements RedisService {

    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    @Qualifier("redisTemplate1")
    private RedisTemplate<String, String> redisTemplate1;
    @Autowired
    @Qualifier("redisTemplateValWithStr")
    private RedisTemplate<String, String> redisTemplateValWithStr;

    /**
     * 反序列化
     *
     * @param bytes
     * @return
     */
    public static Object unserialize(byte[] bytes) {
        ByteArrayInputStream bais = null;
        try {
            // 反序列化
            bais = new ByteArrayInputStream(bytes);
            ObjectInputStream ois = new ObjectInputStream(bais);
            return ois.readObject();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            try {
                bais.close();
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }

        }
        return null;
    }

    @Override
    public void add(String key, String value) {

        ValueOperations<String, String> valueOperation = redisTemplate.opsForValue();
        valueOperation.set(key, value);
    }

    @Override
    public void addMain(String key, String value, Integer seconds) {
        ValueOperations<String, String> valueOperation = redisTemplate1.opsForValue();
        valueOperation.set(key, value, seconds, TimeUnit.SECONDS);

    }

    @Override
    public String get(String key) {
        ValueOperations<String, String> valueOperation = redisTemplate.opsForValue();
        return valueOperation.get(key);
    }

    @Override
    public Long getAtomicLong(String key) {
        try {
            RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
            Long value = entityIdCounter.get();
            return value;
        }catch (Exception e){
            log.error("getAtomicLong error",e);
            return null;
        }
    }

    @Override
    public String getWay(String key) {
        ValueOperations<String, String> valueOperation = redisTemplate1.opsForValue();
        return valueOperation.get(key);
    }

    @Override
    public String hash_get(String hashId, String key) {
        HashOperations<String, String, String> hashOperations = redisTemplate.opsForHash();
        return hashOperations.get(hashId, key);
    }

    @Override
    public boolean hash_incr(String key, String filed, Long delta){
        HashOperations<String, String, Long> hashOperations = redisTemplateValWithStr.opsForHash();
        return hashOperations.increment(key,filed,delta) > 0;
    }

    @Override
    public Set<String> keys(String keyPattern){
        return redisTemplateValWithStr.keys(keyPattern);
    }

    @Override
    public Map<String,String> getHashEntries(String key){
        HashOperations<String, String, String> hashOperations = redisTemplateValWithStr.opsForHash();
        return hashOperations.entries(key);
    }

    @Override
    public void setHashFiled(String key, String filed, String value) {
        HashOperations<String, String, String> hashOperations = redisTemplateValWithStr.opsForHash();
        hashOperations.put(key,filed,value);
    }

    @Override
    public void incr(String key){
        redisTemplateValWithStr.opsForValue().increment(key);
    }
    @Override
    public String getWithStr(String key){
        return redisTemplateValWithStr.opsForValue().get(key);
    }

    @Override
    public String getMain(String hashId, String key) {
        HashOperations<String, String, String> hashOperations = redisTemplate1.opsForHash();
        return hashOperations.get(hashId, key);
    }

    @Override
    public Map<String, String> hash_getAll(String hashId) {
        HashOperations<String, String, String> hashOperations = redisTemplate.opsForHash();
        return hashOperations.entries(hashId);
    }

    @Override
    public void add(String key, String value, long seconds) {
        ValueOperations<String, String> valueOperation = redisTemplate.opsForValue();
        valueOperation.set(key, value, seconds, TimeUnit.SECONDS);
    }

    @Override
    public void del(String key) {
        redisTemplate.delete(key);
    }

    @Override
    public Long incr(String key, long liveTime) {
        RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
        Long increment = entityIdCounter.getAndIncrement();

        if ((null == increment || increment.longValue() == 0) && liveTime > 0) {//初始设置过期时间
            entityIdCounter.expire(liveTime, TimeUnit.SECONDS);
        }
        return increment;
    }

    @Override
    public String getSecondHash(String key, String field) {
        HashOperations<String, String, String> hashOperations = redisTemplate.opsForHash();
        String result = hashOperations.get(key, field);
        if (result == null) {
            return null;
        }
        return result;
    }

    @Override
    public boolean setNx(String key, String value, long liveTime) {
        ValueOperations<String, String> valueOperation = redisTemplate.opsForValue();
        boolean result = valueOperation.setIfAbsent(key, value, liveTime, TimeUnit.SECONDS);
        return result;

    }

    @Override
    public void lPushWithStr(String keyName, String val) {
        redisTemplateValWithStr.opsForList().leftPush(keyName, val);
    }

    @Override
    public List<String> lRangeWithStr(String key,Integer start,Integer end){
       return redisTemplateValWithStr.opsForList().range(key,start,end);
    }

    @Override
    public String lPopWithStr(String uKey) {
        return redisTemplateValWithStr.opsForList().leftPop(uKey);
    }

    @Override
    public void lRemWithStr(String uKey, String val) {
        redisTemplateValWithStr.opsForList().remove(uKey, 1, val);
    }

    @Override
    public Long getExpiration(String key) {
        return redisTemplate.getExpire(key);
    }

    @Override
    public void addSet(String key, Date expireDate, String... values){
        redisTemplate.opsForSet().add(key,values);
        redisTemplate.expireAt(key,expireDate);
    }

    @Override
    public boolean hasElementSet(String key,String value){
        return Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(key, value));
    }

    @Override
    public boolean hasKey(String key) {
        return Boolean.TRUE.equals(redisTemplate.hasKey(key));
    }
}